package com.example.demo.listToTree;

import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSON;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author leiliang
 * @version 1.0
 * @Description list数据转Tree结构
 * @date 2021/11/29 19:11
 */
public class ListToTreeUtils {

    /**
     * list转Tree
     *
     * @param nodes 节点集合
     * @param <T>   节点类型
     *
     * @return 返回树形结构构成的节点集合
     */
    public static <T extends TreeNode<T, Long>> List<T> listToTree (List<T> nodes) {
        return listToTree(nodes, node -> 0 ==  node.getParentId());
    }




    /**
     * list转Tree
     *
     * @param nodes       节点集合
     * @param rootDecider 根节点判定函数，该函数以节点对象为参数，返回 true 时表示该节点属于根节点的直接子节点
     * @param <T>         节点类型
     * @param <ID>        节点 ID 的类型
     *
     * @return 返回树形结构构成的节点集合
     */
    public static <T extends TreeNode<T, ID>, ID> List<T> listToTree (List<T> nodes, Function<T, Boolean> rootDecider) {
        Map<ID, List<T>> nodeByParentIdMap = nodes.stream()
                .collect(Collectors.groupingBy(TreeNode::getParentId));
        nodes.forEach(node -> node.setChildren(nodeByParentIdMap.get(node.getId())));
        List<T> list = new ArrayList<>();
        for (T node : nodes) {
            if (rootDecider.apply(node)) {
                list.add(node);
            }
        }
        return list;
    }


    /**
     * 树状list转普通list
     * @param
     * @return
     */
    public static <T extends TreeNode<T, ID>, ID> List<T> treeToList (List<T> tree) {
        List<T> nodes = new ArrayList<>();
        for (T node : tree) {
            nodes.add(node);

            List<T> children = node.getChildren();
            if (CollUtil.isNotEmpty(children)) {
                nodes.addAll(treeToList(children));
                node.setChildren(null);
            }
        }
        return nodes;
    }

    public static void main(String[] args) {
        List<Zone> zoneList = new ArrayList<>();
        zoneList.add(new Zone(1L, "上海", 0L));
        zoneList.add(new Zone(2L, "北京", 0L));
        zoneList.add(new Zone(3L, "河南", 0L));
        zoneList.add(new Zone(31L, "郑州", 3L));
        zoneList.add(new Zone(32L, "洛阳", 3L));
        zoneList.add(new Zone(321L, "洛龙", 32L));
        zoneList.add(new Zone(11L, "松江", 1L));
        zoneList.add(new Zone(111L, "泗泾", 11L));

        System.out.println("=======================2========================");

        System.out.println("===========================4===================");
        List<Zone> rootZone3_01 = listToTree(zoneList); // 测试第三种方法
        System.err.println(JSON.toJSONString(rootZone3_01));

    }
}
